<?php

namespace p5\objects;

/**
 * Created by PhpStorm.
 * User: simon
 * Date: 2015/11/23
 * Time: 9:40
 */
class TimeUtils
{
    private static $language = "zh";

    public static function format_date($d)
    {
        if (gettype($d) == "integer") {
            return date('Y-m-d', $d);
        }
        if (!empty($d) && is_string($d) && strlen($d) > 10) {
            return substr($d, 0, 10);
        }
        return $d;
    }

    public static function format_time($d)
    {
        if (gettype($d) == "integer") {
            return date('Y-m-d H:i:s', $d);
        }
        if ($d != "") {
            return substr($d, 0, 16);
        }
        return $d;
    }

    public static function get_milli_time()
    {
        $time_test = microtime();
        list($ten_thousand, $sec) = explode(" ", $time_test);
        $time = ((float)$ten_thousand + (float)$sec);
        return round($time * 1000);
    }

    public static function current_date()
    {
        return date('Y-m-d');
    }

    public static function current_hour_minute()
    {
        return date('Hi');
    }

    public static function yesterday()
    {
        return TimeUtils::offset_n_day(-1);
    }

    public static function offset_n_day($n, $time = "")
    {
        $time = empty($time) ? time() : $time;
        if (is_string($time)) {
            $time = self::string_to_date($time);
        }
        return date('Y-m-d', $time + $n * 24 * 60 * 60);
    }

    public static function tomorrow()
    {
        return TimeUtils::offset_n_day(1);
    }

    public static function current_datetime()
    {
        return date('Y-m-d H:i:s');
    }

    public static function current_ymdhi()
    {
        return date('Y-m-d H:i');
    }

    public static function current_time()
    {
        return date('Y-m-d H:i:s');
    }

    public static function time_add($time, $offset, $unit = 'minute', $format = 'Y-m-d H:i:s')
    {
        $t1 = TimeUtils::time_offset($time, $offset, $unit);
        return date($format, $t1);
    }

    public static function time_offset($time, $offset, $unit = "minute")
    {
        $units = array("second" => 1, "minute" => 60, "hour" => 3600, "day" => 3600 * 24);
        if (gettype($time) == "integer") {
            $t1 = $time;
        } else {
            $t1 = strtotime($time);
        }
        $t1 += $offset * $units[$unit];;
        return $t1;
    }

    //获得下周的第一天
    public static function get_next_week_begin()
    {
        $t = time();
        while (true) {
            if (!TimeUtils::is_this_week($t)) {
                return $t;
            }
            $t = TimeUtils::time_offset($t, 1, "day");
        }
    }


    private static $short_months = array("jan" => "01", "feb" => "02", "mar" => "03", "apr" => "04", "may" => "05", "jun" => "06", "jul" => "07", "aug" => "08", "sept" => "09", "oct" => "10", "nov" => "11", "dec" => "12");
    private static $long_months = array("January" => "01", "February" => "02", "March" => "03", "April" => "04", "May" => "05", "June" => "06", "July" => "07", "August" => "08", "September" => "09", "October" => "10", "November" => "11", "December" => "12");


    /**
     * @param $string
     * @return int
     */
    public static function string_to_date($string)
    {
        global $short_months, $long_months;

        $string = trim($string);
        $matrix = array();
        $regexp = "/([\d]{1,2} )([a-zA-Z]{3,4} )([\d]{4} )([\d]{1,2}:[\d]{1,2}:[\d]{1,2})/i";
        if (preg_match($regexp, $string, $matrix) > 0) {
            $key = trim(strtolower($matrix[2]));
            $timestr = trim($matrix[3]) . "-" . $short_months[$key] . "-" . trim($matrix[1]) . " " . trim($matrix[4]);
            return strtotime($timestr);
        }
        //1354897326
        $regexp = "/([\d]{10})/i";
        if (preg_match($regexp, $string, $matrix) > 0) {
            return $matrix[1] * 1;
        }
        return strtotime($string);
    }

    public static function is_today($time)
    {
        return date('Y-m-d') == date('Y-m-d', $time);
    }

    public static function is_yesterday($time)
    {
        return date('Y-m-d', time() - 24 * 60 * 60) == date('Y-m-d', $time);
    }

    public static function is_this_week($time)
    {
        return date('Y-W', time()) == date('Y-W', $time);
    }

    public static function is_last_week($time)
    {
        return date('Y-W', time() - 7 * 24 * 60 * 60) == date('Y-W', $time);
    }

    public static function is_last_7_day($time)
    {
        return TimeUtils::check_day_offset($time, 7);
    }

    public static function is_last_30_day($time)
    {
        return TimeUtils::check_day_offset($time, 30);
    }

    public static function check_day_offset($time, $days)
    {
        return time() - $time < $days * 24 * 60 * 60;
    }

    public static function is_this_month($time)
    {
        return date('Y-m', time()) == date('Y-m', $time);
    }

    public static function is_last_month($time)
    {
        return date('Y-m', time()) * 1 - date('Y-m', $time) * 1 == 1;
    }

    public static function is_this_year($time)
    {
        return date('Y', time()) == date('Y', $time);
    }

    public static function is_last_year($time)
    {
        return date('Y', time()) - date('Y', $time) == 1;
    }

    /*
    获取本周的日期
    */
    public static function get_current_week_first_day()
    {
        $current = date('w', time());
        // print_html($current);
        $offset = ($current) * 24 * 60 * 60;
        return date('Y-m-d', time() - $offset);
    }

    public static function get_current_week_days()
    {
        $current = date('w', time());
        $first = time() - ($current - 1) * 24 * 60 * 60;
        return TimeUtils::get_continue_days($first, 7);
    }

    /*
    获取指定日期的星期一
    */
    public static function get_monday($date)
    {
        $datetime = strtotime($date);
        $current = date('w', $datetime);
        $offset = ($current - 1) * 24 * 60 * 60;
        if ($current == 0){
            $offset = 6 * 24 * 60 * 60;
        }
        return date('Y-m-d', $datetime - $offset);
    }
    /*
    获取指定日期的星期天
    */
    public static function get_sunday($date)
    {
        $datetime = strtotime($date);
        $current = date('w', $datetime);
        $offset = (7 - $current) * 24 * 60 * 60;
        if ($current == 0){
            $offset = 0;
        }
        return date('Y-m-d', $datetime + $offset);
    }

    public static function get_week_days($date)
    {
        $monday = TimeUtils::get_monday($date);
        return TimeUtils::get_continue_days($monday, 7);
    }

    public static function get_last_week_first_day()
    {
        $current = date('w', time());
        // print_html($current);
        $offset = ($current + 6) * 24 * 60 * 60;
        return date('Y-m-d', time() - $offset);
    }

    public static function get_last_week_last_day()
    {
        $current = date('w', time());
        // print_html($current);
        $offset = $current * 24 * 60 * 60;
        return date('Y-m-d', time() - $offset);
    }

    public static function get_next_week_first_day()
    {
        $current = date('N', time());
        // echo $current ;
        $offset = ($current - 8) * 24 * 60 * 60;
        return date('Y-m-d', time() - $offset);
    }

    public static function get_last_week_days()
    {
        $current = date('w', time());
        $first = time() - ($current + 7) * 24 * 60 * 60;
        return TimeUtils::get_continue_days($first, 7);
    }

    public static function get_next_week_days()
    {
        $current = date('w', time());
        $first = time() + (7 - $current) * 24 * 60 * 60;
        return TimeUtils::get_continue_days($first, 7);
    }

    public static function get_month_first_day($date = "")
    {
        if (empty($date)) {
            $date = date("Y-m");
        } else {
            $date = date('Y-m', strtotime($date));
        }
        return $date . "-01";
    }

    public static function get_month_last_day($date = "")
    {
        if (empty($date)) {
            $date = date("Y-m");
            $lastDay = date("t");
        } else {
            $date = date('Y-m', strtotime($date));
            $lastDay = date("t", strtotime($date));
        }

        return $date . "-" . $lastDay;
    }


    public static function get_current_month_first_day()
    {
        return date('Y-m', time()) . "-01";
    }

    public static function get_next_month_first_day($time = "")
    {
        if (empty($time)) {
            $time = time();
        }
        if (is_string($time)) {
            $time = self::string_to_date($time);
        }
        $year = date('Y', $time);
        $month = date('m', $time);
        if ($month == 12) {
            return ($year * 1 + 1) . "-01-01";
        }
        return ($year * 1) . '-' . (($month * 1 + 1) >= 10 ? "" : "0") . ($month * 1 + 1) . "-01";
    }

    public static function get_current_month_days()
    {
        $prefix = date('Y-m', time()) . "-";
        $days = array();
        $max = date('t', time());
        for ($i = 1; $i <= $max; $i++) {
            array_push($days, $prefix . ($i > 9 ? "" : "0") . $i);
        }
        return $days;
    }

    public static function get_last_month_first_day()
    {
        $t = strtotime(TimeUtils::get_current_month_first_day()) - 24 * 60 * 60;
        return date('Y-m', $t) . "-01";
    }

    public static function get_last_month_days()
    {
        $t = strtotime(TimeUtils::get_current_month_first_day()) - 24 * 60 * 60;
        $prefix = date('Y-m', $t) . "-";
        $days = array();
        $max = date('t', $t);
        for ($i = 1; $i <= $max; $i++) {
            array_push($days, $prefix . ($i > 9 ? "" : "0") . $i);
        }
        return $days;
    }


    public static function get_last_n_days($n)
    {
        return TimeUtils::get_continue_days(time(), $n, false);
    }

    /**
     * 获取从某天开始，连续n天的日期
     */
    public static function get_continue_days($first, $next_count, $asc = true)
    {
        $days = array();
        for ($i = 0; $i < $next_count; $i++) {
            $n = $i;
            if (!$asc) {
                $n = $i - 6;
            }
            $offset = $n * 24 * 60 * 60;
            $day = date('Y-m-d', $first + $offset);
            array_push($days, $day);
        }
        return $days;
    }

    public static function get_search_days()
    {
        return [
            "today" => "今天"
            , "yesterday" => "昨天"
            , "this_week" => "本周"
            , "last_week" => "上周"
            , "last_7_day" => "近7天"
            , "this_month" => "这个月"
            , "last_month" => "上个月"
            , "last_30_day" => "近30天"
            , "this_year" => "今年"
            , "last_year" => "去年"
        ];
    }


    static public function to_kind_time($time, $withMinute = true, $language = "zh")
    {
        $list = [$time];
        self::to_kind_times($list, $withMinute, $language);
        return $list[0];
    }

    private static $kindNames = "";

    /**
     * @return array
     */
    public static function getKindNames()
    {
        if (empty(self::$kindNames)) {
            if (self::$language == "en") {
                self::$kindNames = [
                    self::yesterday() => "Yesterday",
                    self::current_date() => "Today",
                    self::tomorrow() => "Tomorrow",
                ];
            } else {
                self::$kindNames = [
                    self::offset_n_day(-2) => "前天",
                    self::yesterday() => "昨天",
                    self::current_date() => "今天",
                    self::tomorrow() => "明天",
                    self::offset_n_day(2) => "后天",
                ];
            }
        }
        return self::$kindNames;
    }

    static public function to_kind_times(&$times = [], $withMinute = true, $language = "zh")
    {

        self::setLanguage($language);
        $names = self::getKindNames();
        $size = count($times);
        for ($i = 0; $i < $size; $i++) {
            $time = $times[$i];
            $date = substr($time, 0, 10);
            $hm = substr($time, 11, 5);
            $name = PropertyUtils::get($names, $date, substr($time, 5, 5));
            if ($withMinute) {
                $times[$i] = $name . " " . $hm;
            } else {
                $times[$i] = $name;
            }
        }
    }

    /**
     * 根据日期计算出生日数值，如 3岁1个月birth_md 格式为整形，数值取值范围 100 - 1231 , 后面两位固定为 日，如果日期在10以内则前面加0, 如 101 表示1月1号 , 1011 表示10月11日。所以判断生日方位直接用数值大小比较就好了。
     * @param $date "Y-m-d"格式
     * @return string
     */
    static public function getmd($date = "")
    {
        if (empty($date)) {
            $date = date("Y-m-d");
        }
        $matrix = explode("-", $date);
        $month = $matrix[1];
        if ($month < 10) {
            $month = substr($month, 1, 1);
        }
        $day = $matrix[2];
        $md = $month . $day;
        return $md;

    }

    /**
     * 根据出生日期计算出年龄，如 3岁1个月
     * @param $birth
     * @param bool|true $withMonth
     * @return string
     */
    static public function getAge($birth, $withMonth = true, $unknowDefaultValue = "?", $noShowMoresThan = "")
    {
        if (empty($birth)) {
            return $unknowDefaultValue;
        }
        $matrix = explode("-", $birth);
        $month1 = date("Y") * 12 + date("m");
        $month2 = $matrix[0] * 12 + $matrix[1];
        $months = $month1 - $month2;
        if ($months < 0 || $months > 1800) {
            return $unknowDefaultValue;
        }
        if ($months < 12) {
            return $months . "个月";
        }
        $y = floor($months / 12.0);
        if ($y > 120) {
            return $unknowDefaultValue;
        }
        $m = $months % 12;
        if (!empty($noShowMoresThan) && $y > $noShowMoresThan){
            return "";
        }
        $string = $y . "岁";
        if ($m > 0) {
            if ($withMonth) {
                $string .= $m . "个月";
            } else {
                $string = $y + 1 . "岁";
            }
        }
        return $string;
    }

    public static function justAddMonth($date, $offsetMonths)
    {
        $matrix = explode("-", $date);
        $year = $matrix[0];
        $month = $matrix[1];
        $totalMonths = $year * 12 + ($month * 1 - 1) + $offsetMonths;
        $newYear = floor($totalMonths / 12);
        $newMonth = ($totalMonths % 12) + 1;
        $newMonth = $newMonth >= 10 ? $newMonth : "0" . $newMonth * 1;
        $firstDay = $newYear . "-" . $newMonth . "-01";
        $maxDay = date('t', self::string_to_date($firstDay));
        $matrix[0] = $newYear;
        $matrix[1] = $newMonth;
        $matrix[2] = min($matrix[2] * 1, $maxDay);
        return implode("-", $matrix);
    }

    public static function currentMonthLastDay($date)
    {
        $maxDay = date('t', self::string_to_date($date));
        return substr($date, 0, 8) . $maxDay;
    }

    public static function get_chinese_weekday($time)
    {
        if (gettype($time) == "string") {
            $time = self::string_to_date($time);
        }
        $names = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"];
        $current = date('w', $time);
        return $names[$current];
    }

    public static function getDateDiff($date_1, $date_2, $differenceFormat = '')
    {
        $datetime1 = date_create($date_1);
        $datetime2 = date_create($date_2);
        $interval = date_diff($datetime1, $datetime2);
        if ($differenceFormat != '') {
            return $interval->format($differenceFormat);
        }
        $differenceFormat = "%y-%m-%d-%h-%i-%s";
        $result = explode("-", $interval->format($differenceFormat));
        $result['y'] = $result[0];
        $result['m'] = $result[1];
        $result['d'] = $result[2];
        $result['h'] = $result[3];
        $result['i'] = $result[4];
        $result['s'] = $result[5];
        return $result;
    }

    static public function getIntervalMinutes($fromTime, $toTime)
    {
        return floor((TimeUtils::string_to_date($toTime) - TimeUtils::string_to_date($fromTime)) / 60000);
    }

    static public function getIntervalDays($fromTime, $toTime)
    {
        return floor((TimeUtils::string_to_date($toTime) - TimeUtils::string_to_date($fromTime)) / 86400);
    }

    /**
     * @return string
     */
    public static function getLanguage()
    {
        return self::$language;
    }

    /**
     * @param string $language
     */
    public static function setLanguage($language)
    {
        self::$language = $language;
    }


}
